package org.jwebuilder;

import java.io.Serializable;
import java.util.ArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jcs.JCS;
import org.apache.jcs.access.exception.CacheException;
import org.apache.jcs.engine.behavior.IElementAttributes;
import org.jwebuilder.jcs.JcsRegion;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.servlet.ServletModule;

public class GuiceContext implements Serializable
{
	private static final long serialVersionUID = -1044291220178081139L;

	private static GuiceContext guiceContext;
	private Injector injector;
	private ArrayList<Module> modules = new ArrayList<Module>(2);
	private static final String JCS_ELEMENT_KEY_GUICE_CONTEXT = "GuiceContext";
	private static final Log log;

	static 
    {
        log = LogFactory.getLog(GuiceContext.class);
    }

	protected GuiceContext()
	{
		modules.add(new ServletModule());
		modules.add(new GuiceModule());
	}
	
	/**
	 * 获取 GuiceContext 的实例
	 * @return
	 */
	public static GuiceContext getInstance()
	{
		JCS jcs;
		try
		{
			jcs = JCS.getInstance(JcsRegion.Guice);
		}
		catch (CacheException ex)
		{
			if(log.isErrorEnabled())
			{
				log.error("获取 JCS 实例失败（" + JcsRegion.Guice + "）！", ex);
			}
			throw new RuntimeException(ex);
		}
		synchronized(GuiceContext.class)
		{
			if(guiceContext == null)
			{
				guiceContext = new GuiceContext();
				try
				{
					IElementAttributes elementAttributes = jcs.getDefaultElementAttributes();
					elementAttributes.setIsEternal(true);
					jcs.put(JCS_ELEMENT_KEY_GUICE_CONTEXT, guiceContext, elementAttributes);
				}
				catch (CacheException e)
				{
					if(log.isErrorEnabled())
					{
						log.error("缓存 GuiceContext 的实例失败！", e);
					}
					throw new RuntimeException(e);
				}
			}
		}
		return (GuiceContext)jcs.get(JCS_ELEMENT_KEY_GUICE_CONTEXT);
	}

	/**
	 * 获取注射器
	 * @return
	 */
	public Injector getInjector()
	{
		return injector;
	}

	public void setInjector(Injector injector)
	{
		this.injector = injector;
	}
	
	/**
	 * 添加创建 Injector 时使用的 Guice Module
	 * @param module
	 */
	public void addModule(Module module)
	{
		modules.add(module);
	}
	
	/**
	 * 创建 Injector 的实例
	 * @return
	 */
	public Injector createInjector()
	{
		synchronized(guiceContext)
		{
			guiceContext.injector = Guice.createInjector(Stage.DEVELOPMENT, modules);
		}
		return injector;
	}
}